import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from PIL import Image
# 设置字体为 SimHei（黑体）
plt.rcParams['font.family'] = 'SimSun'
# 创建图形和坐标轴
fig, ax = plt.subplots(figsize=(10, 6))
ax.set_xlim(0, 4*np.pi)
ax.set_ylim(0, 2.5)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_title('摆线动画: $x = \\theta - \\sin\\theta$, $y = 1 - \\cos\\theta$')
ax.grid(True, linestyle='--', alpha=0.7)

# 初始化空线和点
line,  = ax.plot([], [], 'b-', lw=2)
point, = ax.plot([], [], 'ro', markersize=8)
theta_text = ax.text(0.05, 0.95, '', transform=ax.transAxes)

# 初始化函数
def init():
    line.set_data([], [])
    point.set_data([], [])  # 传入空列表而不是None
    theta_text.set_text('')
    return line, point, theta_text

# 动画更新函数
def update(frame):
    theta_max = frame / 10
    theta = np.linspace(0, theta_max, 1000)  # 动态增加θ范围
    x = theta - np.sin(theta)
    y = 1 - np.cos(theta)
    
    line.set_data(x, y)
    # 修复：将单个点放入列表
    point.set_data([x[-1]], [y[-1]])  # 标记当前点
    
    # 显示θ值（以π为单位）
    theta_text.set_text(f'$\\theta = {theta_max:.1f}\\pi$')
    
    # 动态调整坐标轴范围
    if frame > 100:
        # ax.set_xlim(0, (theta_max + 0.1)*np.pi)
        ax.set_xlim(0, 8*np.pi)
    
    return line, point, theta_text

# 创建动画 (θ从0到4π)
# 减少总帧数以加快生成速度
frames = np.arange(0, 252, 1)  # 步长增加到1.5
ani = FuncAnimation(fig, update, frames=frames,
                    init_func=init, blit=True, interval=50)

# 保存为GIF
print("正在生成动画，请稍候...")
gif_path = "cycloid_animation.gif"

try:
    # 使用pillow保存为GIF，降低fps和dpi以减小文件大小
    ani.save(gif_path, writer='pillow', fps=10, dpi=100)
    print(f"动画已成功保存为 {gif_path}")
    
except Exception as e:
    print(f"保存动画时出错: {e}")
    print("尝试使用替代方法保存...")
    
    # 尝试逐帧保存然后组合
    frames = []
    for i in frames:
        update(i)
        fig.canvas.draw()
        frames.append(np.array(fig.canvas.renderer.buffer_rgba()))
    
    # 保存为GIF
    if frames:
        frames[0].save(gif_path, format='GIF', append_images=frames[1:],
                       save_all=True, duration=100, loop=0)
        print(f"使用替代方法保存成功: {gif_path}")
    else:
        print("无法保存动画")